// ==================================================================================
// Shared Genomics Project MPI Codebase
// Version 1.0 30/04/2010
//
// (c) 2010 University of Manchester all rights reserved
//
// This file is distributed under the GNU General Public License, Version 2.  
// Please see the file COPYING.txt for more details
// ==================================================================================

/*!
\file
\brief Main body of the LD sampling program 
*/

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "SMG_All.h"

struct option long_options[] = {
	{ "bmap", required_argument, NULL, 'm' }, // Path to the map file.
	{ "bped", required_argument, NULL, 'p' }, // Path to PED File.
	{ "id", required_argument, NULL, 'i' }, // Run ID
	{ "ldir", required_argument, NULL, 'd'}, // Output direct
	{ "rdir", required_argument, NULL, 'r'}, // Remote Output direct
	{ "ld-window-kb", required_argument, NULL, 'w'}, // Window of consideration when sampling a data-set for LD data.
	{ "ld-window", required_argument, NULL, 'n'}, // N-mer window centered on the anchor SNP.
	{ "snp", required_argument, NULL, 's'}, // SNP identifier to center LD calc on.
	{ "founders", required_argument, NULL, 'f'}, // Path to founders/gender data file.
	{ 0,    0,    0,    0   } 
};

#define NREQUIRED_ARGS 7

void lowercase_string(char *a)
{
	while (*a != '\0') {
		if (isupper (*a)) *a = (char) tolower (*a);
		++a;
	}
}

void lowercase_snp_ids(struct small_locus *map, int nMap) {
	int i;
	if (map == NULL || nMap <= 0) return;
	for (i = 0; i < nMap; i++) lowercase_string(map[i].name);
}

int main(int argc, char *argv[])
{
	BOOL use_snp_tuple_window = FALSE;
	char ch, snp_id[TOKEN_LENGTH], *bpedData = NULL;
	struct selected_options ops;
	int nRequiredArgs = NREQUIRED_ARGS, nMap = 0, snp_indices[3], nSamples = 0, nSNPs = 0, nSex = 0;
	time_t now = time(NULL);
	BOOL jobDone = FALSE, *sex = NULL;
	struct small_locus *map = NULL;

	init_genrand((unsigned long) now);
	options_init(&ops);
	init_int_array(snp_indices, 3, -1);
	*ops.rdir = *ops.ldir = *ops.szRunId = *snp_id = '\0'; 
	ops.verbose = FALSE;

	while ((ch = (char) getopt_long(argc, argv, "m:v:p:f:i:", long_options, NULL)) != -1) {
		int value;
		switch (ch) {
			case 'i':
				strcpy(ops.szRunId, optarg);
				nRequiredArgs--;
				break;
			case 'm':
				strcpy(ops.szBmapFileName, optarg);
				nRequiredArgs--;
				break;
			case 'd':
				strcpy(ops.ldir, optarg);
				nRequiredArgs--;
				break;
			case 'p':
				strcpy(ops.szBpedFileName, optarg);
				nRequiredArgs--;
				break;
			case 'r': 
				strcpy(ops.rdir, optarg);
				nRequiredArgs--;
				break;
			case 'w':
				value = atoi(optarg);
				if (value >= 0) ops.disp_r_window_kb = value;
				break;
			case 's':
				if (strlen(optarg) > 0) {
					strcpy(snp_id, optarg);
					nRequiredArgs--;
				}
				break;
			case 'f': // path to the founders/gender file.
				strcpy(ops.szFoundersFileName, optarg);
				nRequiredArgs--;
				break;
			case 'n':
				value = atoi(optarg);
				if (value > 0) {
					ops.disp_r_window_snp = value;
					use_snp_tuple_window = TRUE;
				}
				
				break;
			default:
				break;
		}
	}
	
	// If not all required supplied, stop and moan.
	if (nRequiredArgs != 0) return -1;

	map = bmapfile_load(&ops, &nMap);
	sex = foundersfile_load(&ops, &nSex);
	if (map != NULL && sex != NULL) {
		BOOL got_snp_indices = FALSE;

		lowercase_snp_ids(map, nMap);
		lowercase_string(snp_id);
		if (!use_snp_tuple_window) got_snp_indices = ld_data_get_indices(map, nMap, snp_id, ops.disp_r_window_kb, &snp_indices[0], &snp_indices[1], &snp_indices[2]) ? TRUE : FALSE;
		else got_snp_indices = ld_data_get_indices_nmer(map, nMap, snp_id, ops.disp_r_window_snp, &snp_indices[0], &snp_indices[1], &snp_indices[2]) ? TRUE : FALSE;

		if(got_snp_indices) {
			FILE *in = fopen(ops.szBpedFileName, "rb");
			if (in != NULL) {
				if (bpedfile_read_header(in, &nSNPs, &nSamples)) {
					if (nSNPs == nMap && nSex == nSamples) {
						bpedData = bpedfile_fseek(in, nSNPs, nSamples, snp_indices[0], snp_indices[1]);	
						if (ld_data_create_tpedfile(&ops, bpedData, map, nMap, snp_indices[0], snp_indices[1], nSamples)) {
							if (ld_data_create_tfamfile(&ops, sex, nSex)) {
								if (ld_data_create_gphefile(&ops, sex, nSex)) {
									ld_data_create_smapfile(&ops, map, nMap, snp_indices[0], snp_indices[1], snp_indices[2]);
									jobDone = TRUE;
								}
							}
						}
					}
				}
				fclose(in);
			}
		}
	}
	
	if (map != NULL) free(map);
	if (bpedData != NULL) free(bpedData);
	if (sex != NULL) free(sex);

	if (jobDone) return 0;
	else return -1;
}